#include "ui_mywidget.h"
#include "mywidget.h"

extern QMap<QString,QString>Map_AvoidReopenWidgets;

MyWidget::MyWidget(QWidget *parent, QString ip, QString name): QWidget(parent),
    ui(new Ui::MyWidget), var_timer(nullptr), var_ip(ip),
    var_name(name), var_timeWasteNum(0)
{
    ui->setupUi(this);
    ui->label_result->setText(tr("无故障"));
    ui->label_time->setText(tr("00 : 00 : 00"));
    setWindowTitle(tr("节点%1").arg(var_ip));

    var_tcpClient = new TcpClient(var_ip);

    connect(ui->button_collect,&QPushButton::clicked,this,&MyWidget::saveReceieveFiles);
    connect(ui->button_diagnosis,&QPushButton::clicked,this,[&]{emit faultDiagnoseSignal(cmd_faultDiagnosis);});
    connect(&var_dataCollectTime,&QTimer::timeout,this,&MyWidget::updateDataCollectTimeWaste);
    // 线程结束后删除client
    connect(&var_tcpClientThread,&QThread::finished,var_tcpClient,&TcpClient::deleteLater);
    // client发送信号触发Mywidget的槽函数
    connect(var_tcpClient,&TcpClient::tcpStateChanged,this,&MyWidget::tcpConnectStateChanged);
    connect(var_tcpClient,&TcpClient::faultDiagnosisResults,this,&MyWidget::displayDiagnosisResult);
    connect(var_tcpClient,&TcpClient::serverInformation,this,&MyWidget::acceptServerInformation);
    connect(var_tcpClient,&TcpClient::errorOccurred,this,&MyWidget::tcpErrorOccured);
    connect(var_tcpClient,&TcpClient::dataCollectionProgress,this,&MyWidget::setProgressBarValue);
    connect(var_tcpClient,&TcpClient::textLabel,this,[&](QString text){emit textLabel(text);});
    // Mywidget发送号触发client的槽函数
    connect(this,&MyWidget::connectToServer,var_tcpClient,&TcpClient::createConnection);
    connect(this,&MyWidget::disconnectFromServer,var_tcpClient,&TcpClient::closeConnection);
    connect(this,&MyWidget::dataCollectStart,var_tcpClient,&TcpClient::dataCollection);
    connect(this,&MyWidget::dataCollectStop,var_tcpClient,&TcpClient::sendCommand);
    connect(this,&MyWidget::faultDiagnoseSignal,var_tcpClient,&TcpClient::sendCommand);
    connect(this,&MyWidget::cancelTransimition,var_tcpClient,&TcpClient::sendCommand);

    var_tcpClient->moveToThread(&var_tcpClientThread);
    var_tcpClientThread.start();
    // emit connectToServer(var_ip);                     // 在构造函数内直接发射信号可能会失效
    QTimer::singleShot(10, var_tcpClient, &TcpClient::createConnection);// 利用单次定时器触发
    // 5秒超时则断开连接并进行相关提醒
    QTimer::singleShot(5000, this, [&]{
        if(var_tcpClient->state() == QAbstractSocket::ConnectingState){
            emit disconnectFromServer();
        }
    });
}

MyWidget::~MyWidget()
{
    var_tcpClientThread.quit();
    var_tcpClientThread.wait();
    emit textLabel(tr("节点%1已关闭").arg(var_ip));
    qDebug() << tr("~my widget 析构");
}

void MyWidget::closeEvent(QCloseEvent *event)
{
    if(ui->button_collect->text() == tr("停止采集"))
    {
        QMessageBox::warning(this,tr("警告"),tr("请先停止采集"));
        event->ignore();
        return;
    }
    emit disconnectFromServer();
    Map_AvoidReopenWidgets.remove(var_ip);

    QWidget::closeEvent(event);
}

void MyWidget::tcpConnectStateChanged(QAbstractSocket::SocketState state)
{
    if(state == TcpClient::ConnectedState)
    {
        emit textLabel(tr("成功连接节点%1").arg(var_ip));
        this->show();
        // 每5秒检测是否断连
        var_timer = new QTimer(this);
        connect(var_timer, &QTimer::timeout, var_tcpClient, &TcpClient::createConnection);
        var_timer->start(5000);
    }
    else if(state == TcpClient::ConnectingState)
    {
        emit textLabel(tr("服务器连接中....."));
    }
}

void MyWidget::tcpErrorOccured(QAbstractSocket::SocketError error)
{
    qDebug() << var_tcpClient->errorString();
    if(error == QAbstractSocket::ConnectionRefusedError)
    {
        if(if_messageBoxShown)
            return;
        if(var_timer != nullptr)
        {
            var_timer->stop();
            emit textLabel(tr("连接超时!\n请检查服务器是否开启"));
            QMessageBox msg(QMessageBox::Information,"提示","连接超时!请检查服务器是否开启\n是否重新连接?");
            msg.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
            if_messageBoxShown = true;
            if(msg.exec() == QMessageBox::Yes)
            {
                QTimer::singleShot(0,var_tcpClient,&TcpClient::createConnection);
            }
            else
            {
                this->close();
            }
            if_messageBoxShown = false;
        }
        else
        {
            emit textLabel(tr("连接超时!\n请检查服务器是否开启"));
            QMessageBox::information(this,"提示","连接超时!\n请检查服务器是否开启");
            Map_AvoidReopenWidgets.remove(var_ip);
        }
    }
    else
    {
        emit textLabel(var_tcpClient->errorString());
        // QMessageBox::information(this,"提示",var_tcpClient->errorString());
    }
}

void MyWidget::displayDiagnosisResult(QString result)
{
    ui->label_result->setText(result);
}

void MyWidget::acceptServerInformation(QString result)
{
    if(result == tr("数据采集开始"))
    {
        ui->button_collect->setText(tr("停止采集"));
        var_dataCollectTime.setInterval(999);
        var_dataCollectTime.start(); // 计算采集时间
    }
    else
    {
        QMessageBox::warning(this,"警告",result);
    }
}

void MyWidget::saveReceieveFiles()
{
    if(ui->button_collect->text() == tr("开始采集"))
    {
        QString directory = QFileDialog::getExistingDirectory(this, "Select Folder", "./");
        if (!directory.isEmpty())
        {
            // qDebug() << directory;
            emit dataCollectStart(cmd_dataCollectionStart,directory+"/");
        }
    }
    else
    {
        emit dataCollectStop(cmd_dataCollectionStop);
        var_dataCollectTime.stop();
        var_timeWasteNum = 0;
        ui->label_time->setText(tr("00 : 00 : 00"));
        ui->button_collect->setText(tr("开始采集"));
        ui->button_collect->setStyleSheet("color: lightgray;");
        ui->button_collect->setEnabled(false);
        // 显示进度条
        var_progress = new QProgressDialog("正在采集数据...","取消",0,100,this);
        connect(var_progress,&QProgressDialog::canceled,this,&MyWidget::cancelFileTransimit);
        connect(var_progress,&QProgressDialog::destroyed,this,[&]{qDebug() << "QProgress Close........";});
        var_progress->setAutoReset(false);
        var_progress->setValue(0);
        var_progress->show();
    }
}

void MyWidget::updateDataCollectTimeWaste()
{
    ++var_timeWasteNum;

    QString hours = QString::number(var_timeWasteNum / 3600);
    QString minutes = QString::number((var_timeWasteNum % 3600) / 60);
    QString seconds = QString::number(var_timeWasteNum % 60);

    QString timeString = tr("%1 : %2 : %3").arg(hours,2,'0').arg(minutes,2,'0').arg(seconds,2,'0');
    ui->label_time->setText(timeString);
}

void MyWidget::setProgressBarValue(float speed, float receiveSize, float totalSize)
{
    if(var_progress != nullptr)
    {
        // 设置提示信息
        int remainTime = totalSize/speed/1000 - receiveSize/speed/1000 + 0.5;
        var_progress->setLabelText(tr("已接收 %1MB (%2MB/S)\n共%3MB  剩余用时: %4S")
                                       .arg(receiveSize / (1024 *1024),0,'f',2)
                                       .arg(speed * 1000 / (1024 *1024),0,'f',2)
                                       .arg(totalSize / (1024 *1024),0,'f',2)
                                       .arg(remainTime+1)); // +1的作用是最后一秒不显示0秒
        // 设置进度条
        int value = receiveSize / (totalSize - 0.00001) * 100;
        var_progress->setValue(value);
        if(var_progress->value() >= var_progress->maximum())
        {
            var_progress->setLabelText(tr("数据接收完毕"));
            var_progress->setCancelButtonText(tr("关闭"));
        }
    }
}

void MyWidget::cancelFileTransimit()
{
    ui->button_collect->setEnabled(true);
    ui->button_collect->setStyleSheet("color: black;");
    if(var_progress->labelText() != tr("数据接收完毕"))
    {
        emit cancelTransimition(cmd_stopTransmition);
        QMetaObject::invokeMethod(var_tcpClient,"createConnection");
        // var_tcpClient->abort();
        // var_tcpClient->connectToHost(var_ip,TCP_SERVER_PORT);
    }
    delete var_progress;
    var_progress = nullptr;
}
